package com.scenic.rd_android;


import android.app.LoaderManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

import com.nova.scenic.projectlibs.util.adapter.SimpleAdapter;
import com.nova.scenic.projectlibs.util.adapter.SimpleRecyclerAdapter;
import com.nova.scenic.projectlibs.util.collection.Collections;
import com.nova.scenic.projectlibs.util.debug.MonitorMemoryService;
import com.nova.scenic.projectlibs.util.debug.MyLog;
import com.nova.scenic.projectlibs.util.io.StreamUtil;
import com.nova.scenic.projectlibs.util.resloader.AsyncTaskLoader;
import com.nova.scenic.projectlibs.widget.BaseRecycleView;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

//adb connect 127.0.0.1:21503
public class RDActivity extends BaseActivity {

    public static String packageName;
    private static final String TAG = "RDActivity";
    private static final int LOAD_ID_ACTIVITY_INFO = 1;
    private static final int LOAD_ID_ASSETS_STRING = 2;
    private static final int LOAD_ID_ACTIVITY_FOLDS = 3;

    private MyAdapter.ListViewAdapter myAdapter;
    private MyAdapter.RecyclerAdapter recyclerAdapter;
    private MyAdapter.DropViewAdapter mDropAdapter;

    private String showListFilter;

    private List<MyAdapter.ShowListEntity> mAllActivates = new ArrayList<>();

    MyLog myLog = new MyLog("TTTTTT");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rd);
        packageName = getPackageName();
        initUI();

        checkSpecificLauncher();

        MonitorMemoryService.startActionMonitorMemory(getApplicationContext());
        getLoaderManager().restartLoader(LOAD_ID_ACTIVITY_INFO, null, new MyLoadCallback());
        getLoaderManager().restartLoader(LOAD_ID_ACTIVITY_FOLDS, null, new MyLoadCallback());

        Bundle bundle = new Bundle();
        bundle.putBoolean("showAssetsList", false);
        getLoaderManager().restartLoader(LOAD_ID_ASSETS_STRING, bundle, new MyLoadCallback());
        myLog.info("======================");

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        getLoaderManager().destroyLoader(LOAD_ID_ACTIVITY_INFO);
        getLoaderManager().destroyLoader(LOAD_ID_ACTIVITY_FOLDS);
        getLoaderManager().destroyLoader(LOAD_ID_ASSETS_STRING);

        MonitorMemoryService.stopActionMonitorMemory(getApplicationContext());
    }

    private void initUI() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.id_toolbar);
        setSupportActionBar(toolbar);
        ActionBar ab = getSupportActionBar();
        ab.setHomeAsUpIndicator(R.drawable.ic_menu);
        ab.setDisplayHomeAsUpEnabled(true);
        ab.setDisplayOptions(ab.getDisplayOptions() | ActionBar.DISPLAY_SHOW_CUSTOM);
        ab.setCustomView(R.layout.actionbar_rd_activity);

        mDropAdapter = new MyAdapter.DropViewAdapter(getApplicationContext(), null);

        AutoCompleteTextView autoCompleteTextView = (AutoCompleteTextView) ab.getCustomView().findViewById(R.id.id_autocomplete);
        autoCompleteTextView.setAdapter(mDropAdapter);

        Spinner spinner = (Spinner) ab.getCustomView().findViewById(R.id.id_spinner);
        spinner.setAdapter(mDropAdapter);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                MyLog.i(TAG, "onItemSelected " + position);
                showListFilter = ((String) parent.getItemAtPosition(position)).trim();
                if (mAllActivates != null) {
                    refreshData(mAllActivates);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                MyLog.i(TAG, "onNothingSelected ");
            }
        });


        ListView mListView = (ListView) findViewById(R.id.id_listView_rd_list);
        BaseRecycleView mRecyclerView = (BaseRecycleView) findViewById(R.id.id_recyclerView);
        final DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.id_drawerLayout);
        NavigationView navigationView = (NavigationView) findViewById(R.id.new_view);
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem item) {
                return execute(item);
            }

            private boolean execute(MenuItem item) {
                MyLog.i(TAG, "onNavigationItemSelected " + item.getItemId());
                switch (item.getItemId()) {
                    case R.id.change_data_source_from_manifest: {
                        MyLog.i(TAG, "change the data source");
                        mDrawerLayout.closeDrawers();
                        Loader<Object> loader = getLoaderManager().getLoader(LOAD_ID_ACTIVITY_INFO);
                        loader.forceLoad();
                    }

                    break;
                    case R.id.change_data_source_from_assert: {
                        mDrawerLayout.closeDrawers();
                        Loader<Object> loader = getLoaderManager().getLoader(LOAD_ID_ASSETS_STRING);
                        loader.forceLoad();
                    }
                    break;
                }

                return false;
            }
        });

        myAdapter = new MyAdapter.ListViewAdapter(getApplicationContext());
        mListView.setAdapter(myAdapter);
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                execute(parent, position);
            }

            private void execute(AdapterView<?> parent, int position) {
                MyAdapter.ShowListEntity info = (MyAdapter.ShowListEntity) parent.getItemAtPosition(position);
                Intent startIntent = new Intent();

                String name = info.activityName;
                startIntent.setComponent(new ComponentName(RDActivity.this, name));
                startActivity(startIntent);
            }
        });

        mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));

        recyclerAdapter = new MyAdapter.RecyclerAdapter(getApplicationContext());
        mRecyclerView.setAdapter(recyclerAdapter);
        //设置Item增加、移除动画
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        //添加分割线
        mRecyclerView.addItemDecoration(new BaseRecycleView.DividerItemDecoration(getApplicationContext(),
                BaseRecycleView.DividerItemDecoration.HORIZONTAL_LIST));
        mRecyclerView.setOnItemClickListener(new BaseRecycleView.OnItemClickListener() {
            @Override
            public void onItemClick(RecyclerView parent, View view, int position) {
                execute(position);
            }

            private void execute(int position) {
                MyAdapter.ShowListEntity info = recyclerAdapter.getItem(position);
                Intent startIntent = new Intent();

                String name = info.activityName;
                startIntent.setComponent(new ComponentName(RDActivity.this, name));
                startActivity(startIntent);
            }
        });

    }

    private void checkSpecificLauncher() {

        ApplicationInfo appInfo = null;
        try {
            appInfo = this.getPackageManager()
                    .getApplicationInfo(getPackageName(),
                            PackageManager.GET_META_DATA);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        try {
            String msg = appInfo.metaData.getString("launcherActivity");
            MyLog.i(TAG, "launcherActivity value is " + msg);
            if (msg != null && !msg.equals("")) {
                Intent startIntent = new Intent();
                startIntent.setComponent(new ComponentName(getPackageName(), msg));
                startActivity(startIntent);
            }
        } catch (Exception e) {
            MyLog.e(TAG, e.toString());
        }
    }

    private void refreshData(List<MyAdapter.ShowListEntity> mList) {

        Comparator<MyAdapter.ShowListEntity> comparator = new Comparator<MyAdapter.ShowListEntity>() {
            @Override
            public int compare(MyAdapter.ShowListEntity lhs, MyAdapter.ShowListEntity rhs) {
                return execute(lhs, rhs);
            }

            private int execute(MyAdapter.ShowListEntity lhs, MyAdapter.ShowListEntity rhs) {
                String name1 = lhs.activityName;
                String name2 = rhs.activityName;

                if (lhs.labelRes > 0) {
                    name1 = lhs.labelName.toString();
                }

                if (rhs.labelRes > 0) {
                    name2 = rhs.labelName.toString();
                }
                return name1.compareTo(name2);
            }
        };

        if (showListFilter != null && !showListFilter.equals("ALL")) {
            List<MyAdapter.ShowListEntity> mViewList = new ArrayList<>();
            for (MyAdapter.ShowListEntity en : mList) {
                String name = en.activityName;

                if (name.contains(showListFilter)) {
                    mViewList.add(en);
                }
            }
            java.util.Collections.sort(mViewList, comparator);
            myAdapter.notifyDataSetChanged(mViewList);
            recyclerAdapter.updateAll(mViewList);
        } else {
            java.util.Collections.sort(mList, comparator);

            myAdapter.notifyDataSetChanged(mList);
            recyclerAdapter.updateAll(mList);
        }
    }
    private class MyLoadCallback implements LoaderManager.LoaderCallbacks {
        @Override
        public Loader onCreateLoader(int id, Bundle args) {
            MyLog.i(TAG, "onCreateLoader " + id);
            Loader loader;
            Context context = RDActivity.this;
            switch (id) {
                case RDActivity.LOAD_ID_ACTIVITY_INFO:
                    loader = new MyLoaders.ResoleInfoLoader(context);
                    break;
                case LOAD_ID_ASSETS_STRING:
                    boolean showAlert = false;
                    if (args != null) {
                        showAlert = args.getBoolean("showAssetsList");
                    }
                    loader = new MyLoaders.AssetsStringLoader(context).setUseTheResult(showAlert);

                    break;
                case LOAD_ID_ACTIVITY_FOLDS:
                    loader = new MyLoaders.ActivatesFoldLoader(context);
                    break;
                default:
                    throw new RuntimeException("id error");
            }
            return loader;
        }

        @Override
        public void onLoadFinished(Loader loader, Object d) {
            List<MyAdapter.ShowListEntity> consumeListData = null;
            switch (loader.getId()) {
                case RDActivity.LOAD_ID_ACTIVITY_INFO:
                    List<ResolveInfo> data1 = (List) d;
                    if (data1.size() > 0) {
                        consumeListData = new ArrayList<>(data1.size());
                        for (ResolveInfo info : data1) {
                            MyAdapter.ShowListEntity entity = new MyAdapter.ShowListEntity();
                            entity.activityName = info.activityInfo.name;
                            entity.labelName = info.activityInfo.loadLabel(getPackageManager());
                            entity.labelRes = info.activityInfo.labelRes;

                            if (entity.activityName.equals(RDActivity.this.getClass().getSimpleName())) {
                                continue;
                            }

                            consumeListData.add(entity);
                        }

                    }

                    break;
                case LOAD_ID_ASSETS_STRING:

                    if (loader instanceof MyLoaders.AssetsStringLoader) {
                        if (((MyLoaders.AssetsStringLoader) loader).useTheResult) {
                            List<String> data2 = (List<String>) d;
                            if (data2.size() > 0) {
                                consumeListData = new ArrayList<>(data2.size());
                                for (String info : data2) {
                                    MyAdapter.ShowListEntity entity = new MyAdapter.ShowListEntity();
                                    entity.activityName = info;

                                    if (entity.activityName.equals(RDActivity.this.getClass().getSimpleName())) {
                                        continue;
                                    }

                                    consumeListData.add(entity);
                                }
                            }

                        }
                    }

                    break;
                case LOAD_ID_ACTIVITY_FOLDS:
                    mDropAdapter.notifyDataSetChanged((List<String>) d);
                    break;
                default:
                    throw new RuntimeException("id error");
            }
            if (consumeListData != null) {
                refreshData(consumeListData);
                mAllActivates.clear();
                mAllActivates.addAll(consumeListData);
            }


        }

        @Override
        public void onLoaderReset(Loader loader) {

        }
    }



    private static class MyAdapter {
        static class ShowListEntity {
            public String activityName;
            public CharSequence labelName;
            public int labelRes;
        }
        private static class RecyclerAdapter extends SimpleRecyclerAdapter<ShowListEntity,SimpleRecyclerAdapter.SimpleViewHold> {

            public RecyclerAdapter(Context context) {
                super(context);
            }

            @Override
            protected void initView(ImageView iv, TextView tx1, TextView tx2, ShowListEntity resolveInfo) {
                super.initView(iv, tx1, tx2, resolveInfo);
                MyAdapter.initView(iv, tx1, tx2, resolveInfo);
            }
        }
        private static class ListViewAdapter extends SimpleAdapter<ShowListEntity> {
            public ListViewAdapter(Context context) {
                super(context, null);
            }

            @Override
            protected void initView(ImageView iv, TextView tx1, TextView tx2, ShowListEntity resolveInfo) {
                super.initView(iv, tx1, tx2, resolveInfo);
                MyAdapter.initView(iv, tx1, tx2, resolveInfo);
            }
        }
        protected static void initView(ImageView iv, TextView tx1, TextView tx2, ShowListEntity resolveInfo) {

            if (resolveInfo.labelRes != 0) {
                tx1.setText(resolveInfo.labelName);
            } else {
                String tmpName = resolveInfo.activityName;
                if (tmpName.contains(packageName)) {
                    tmpName = tmpName.substring(packageName.length());
                }
                tx1.setText(tmpName);
            }
        }

        private static class DropViewAdapter extends SimpleAdapter<String> {
            public DropViewAdapter(Context context, List<String> list) {
                super(context, list);
            }
        }
    }

    private static class MyLoaders {
        private static class AssetsStringLoader extends AsyncTaskLoader<List<String>> {

            /**
             * Stores away the application context associated with context.
             * Since Loaders can be used across multiple activities it's dangerous to
             * store the context directly; always use {@link #getContext()} to retrieve
             * the Loader's Context, don't use the constructor argument directly.
             * The Context returned by {@link #getContext} is safe to use across
             * Activity instances.
             *
             * @param context used to retrieve the application context.
             */
            public AssetsStringLoader(Context context) {
                super(context);

            }

            public boolean useTheResult;

            public AssetsStringLoader setUseTheResult(boolean s) {
                useTheResult = s;
                return this;
            }

            @Override
            public void forceLoad() {
                super.forceLoad();
                useTheResult = true;
            }

            @Override
            public List<String> loadInBackground() {
                AssetManager am = getContext().getApplicationContext().getAssets();
                final List<String> mList = new ArrayList<>();
                try {
                    InputStream input = am.open("manifest_activity");


                    StreamUtil.streamToString(input, new StreamUtil.OnReadStreamHelper() {
                        @Override
                        public boolean isTerminal() {
                            return false;
                        }

                        @Override
                        public void onReaderLine(String line) {
                            mList.add(line);
                        }
                    });


                } catch (IOException e) {
                    e.printStackTrace();
                }
                return mList;
            }
        }
        private static class ResoleInfoLoader extends AsyncTaskLoader<List<ResolveInfo>> {
            /**
             * Stores away the application context associated with context.
             * Since Loaders can be used across multiple activities it's dangerous to
             * store the context directly; always use {@link #getContext()} to retrieve
             * the Loader's Context, don't use the constructor argument directly.
             * The Context returned by {@link #getContext} is safe to use across
             * Activity instances.
             *
             * @param context used to retrieve the application context.
             */
            public ResoleInfoLoader(Context context) {
                super(context);
            }

            @Override
            public List<ResolveInfo> loadInBackground() {
                List<ResolveInfo> data = getResolveInfoList(getContext());
                List<ResolveInfo> myInfo = new ArrayList<>();
                for (ResolveInfo info : data) {
                    if (info.activityInfo.packageName.equals(getContext().getPackageName())) {
                        myInfo.add(info);
                    }
                }
                return myInfo;
            }


        }
        private static class ActivatesFoldLoader extends AsyncTaskLoader<List<String>> {

            public ActivatesFoldLoader(Context context) {
                super(context);
            }

            @Override
            public List<String> loadInBackground() {

                return getActivityFoldList(getContext());
            }
        }
    }

    public static List<ResolveInfo> getResolveInfoList(Context context) {
        synchronized (context.getApplicationContext()) {
            Intent intent = new Intent(Intent.ACTION_MAIN);
            List<ResolveInfo> data = context.getPackageManager().queryIntentActivities(intent, 0);
            MyLog.i(TAG, "data size is " + data.size());
            return data;
        }
    }

    public static List<String> getActivityFoldList(Context context) {
        List<ResolveInfo> data = getResolveInfoList(context);
        Set<String> activityNameFolds = new HashSet<>();
        for (ResolveInfo info : data) {
            if (info.activityInfo.packageName.equals(context.getPackageName())) {
                String activityName = info.activityInfo.name;

                String subtractionString = activityName.substring(context.getPackageName().length());
                if (subtractionString.startsWith(".") && subtractionString.length() > 1) {
                    int index = subtractionString.indexOf('.', 1);
                    if (index > 0) {
                        activityNameFolds.add(" " + subtractionString.substring(1, index));
                    }
                }

            }
        }
        List<String> result = Collections.toList(new ArrayList<String>(), activityNameFolds.iterator());
        java.util.Collections.sort(result);
        result.add(0, "ALL");
        return result;
    }
}
